// Copyright (c) Microsoft Corporation.  All rights reserved.
#pragma once

/*
CViewItem classes are children of CContentView classes. (CContentView, CDialogView and CMenuView)

CViewItem
    CViewTextItem       <txt>
    CViewImageItem      <img>
    CViewBrItem         <br>
    CViewMenuItem       <item> or < div>
*/

// for Text View
#include <imm.h>
#include <richedit.h>
#include <textserv.h>
#include <tom.h>
#include "RichTextHost.h"

#define VIEW_ITEM_FLAG_SELECTED 1

class CContent;
class CContentViewBase;

class CViewItem
{
public:
    CViewItem(CScfElement* pScfElement, CContentViewBase *pParentView)
    : m_pScfElement(pScfElement), m_pParentView(pParentView), m_nWidth(0), m_nHeight(0), m_nYOffset(0)
    {}

    virtual ~CViewItem()
    {}

    virtual HRESULT Initialize() = 0;
    virtual HRESULT CalcItemHeight(HDC hDC, LONG nClientWidth, LONG nClientHeight) = 0;
    virtual HRESULT Draw(HDC hDC, LONG left, LONG top, LONG right, LONG bottom, DWORD dwFlags = 0) = 0;

    LONG GetHeight() { return m_nHeight; }
    
    VOID SetYOffset(int nYOffset) { m_nYOffset = nYOffset; }
    LONG GetYOffset() { return m_nYOffset; }
    
    SCF_ELEMENT_TYPE GetBaseElementType() { return m_pScfElement->GetElementType(); }
    CScfElement* GetBaseElement() { return m_pScfElement; }

    CContentViewBase* GetParentView() { return m_pParentView; }

protected:
    CScfElement* m_pScfElement;
    CContentViewBase* m_pParentView;
    LONG m_nWidth;
    LONG m_nHeight;
    LONG m_nYOffset;
};

// <txt>
class CViewTextItem : public CViewItem
{
public:
    CViewTextItem(CScfElement* pScfElement, CContentViewBase *pParentView)
    : CViewItem(pScfElement, pParentView), m_pTextDoc(NULL), m_pTextSvc(NULL), m_pTextHost(NULL)
    {}

    virtual ~CViewTextItem() { Uninitialize(); }

    VOID Uninitialize();

    virtual HRESULT Initialize();
    virtual HRESULT CalcItemHeight(HDC hDC, LONG nClientWidth, LONG nClientHeight);
    virtual HRESULT Draw(HDC hDC, LONG left, LONG top, LONG right, LONG bottom, DWORD dwFlags);

private:
    ITextDocument* m_pTextDoc;
    ITextServices* m_pTextSvc;
    ITextHost*     m_pTextHost;
};

// <img>
class CViewImageItem : public CViewItem
{
public:
    CViewImageItem(CScfElement* pScfElement, CContentViewBase *pParentView)
    : CViewItem(pScfElement, pParentView)
    {}

    virtual ~CViewImageItem()
    {}
    
    virtual HRESULT Initialize() { return S_OK; }

    virtual HRESULT CalcItemHeight(HDC hDC, LONG nClientWidth, LONG nClientHeight);
    virtual HRESULT Draw(HDC hDC, LONG left, LONG top, LONG right, LONG bottom, DWORD dwFlags);
};

// <br>
class CViewBrItem : public CViewItem
{
public:
    CViewBrItem(CScfElement* pScfElement, CContentViewBase *pParentView)
    : CViewItem(pScfElement, pParentView)
    {
    }

    virtual HRESULT Initialize()
    {
        return S_OK;
    }

    virtual HRESULT CalcItemHeight(HDC hDC, LONG nClientWidth, LONG nClientHeight)
    {
        UNREFERENCED_PARAMETER(nClientWidth);
        UNREFERENCED_PARAMETER(nClientHeight);
        
        TEXTMETRIC tm;
        GetTextMetrics(hDC, &tm);
        m_nWidth = 0;
        m_nHeight = tm.tmHeight;
        return S_OK;
    }

    virtual HRESULT Draw(HDC hDC, LONG left, LONG top, LONG right, LONG bottom, DWORD dwFlags)
    {
        UNREFERENCED_PARAMETER(hDC);
        UNREFERENCED_PARAMETER(left);
        UNREFERENCED_PARAMETER(top);
        UNREFERENCED_PARAMETER(right);
        UNREFERENCED_PARAMETER(bottom);
        UNREFERENCED_PARAMETER(dwFlags);
        
        // do nothing.
        return S_OK;
    }
};

// <item> or <div>
class CViewMenuItem : public CViewItem
{
public:
    CViewMenuItem(CScfElement* pScfElement, CContentViewBase *pParentView)
        : CViewItem(pScfElement, pParentView), m_bLongSingleLine(FALSE), m_nImageWidth(0), m_nImageHeight(0)
    {
    }
    
    virtual HRESULT Initialize()
    {
        return S_OK;
    }
    
    virtual HRESULT CalcItemHeight(HDC hDC, LONG nClientWidth, LONG nClientHeight);
    virtual HRESULT Draw(HDC hDC, LONG left, LONG top, LONG right, LONG bottom, DWORD dwFlags);
    
    BOOL IsLongSingleLineItem() { return m_bLongSingleLine; }
    LONG GetSelectedItemHeight();
    LONG GetItemExtent(HDC hDC);

private:
    /*
        Items without an explicit break should be rendered on only one line. If text is too long to fit onto
        a single line, it should be truncated. When a single-line menu item is selected, however, it should
        wrap onto two lines to allow maximum visibility for any truncated text.
    */
    BOOL m_bLongSingleLine;
    LONG m_nImageHeight;
    LONG m_nImageWidth;
};

